from typing import List, Tuple, Dict, Callable

from Model.RoomModel import RoomModel
from Model.UserModel import DeviceType

# user_id: {
#   token:str,
#   devices:{
#       device_type:address,
#       device_type:address,
#   }
# }
list_client = {}
list_room: List[RoomModel] = []
list_channel = {}


# chat_channel
def CreateChannel(channel_name):
    if not HasChannel(channel_name):
        list_channel[channel_name] = {"leader_user_id": 0, "member": []}
        return True
    return False


def DeleteChannel(channel_name):
    if HasChannel(channel_name):
        del list_client[channel_name]


def HasChannel(channel_name):
    return channel_name in list_channel.keys()


def HasMember(channel_name, user_id):
    return user_id in list_channel[channel_name]['member']


def JoinChannel(channel_name, user_id):
    if HasChannel(channel_name):
        if not HasMember(channel_name, user_id):
            if len(list_channel[channel_name]['member']) <= 0:
                list_channel[channel_name]['leader_user_id'] = user_id
            list_channel[channel_name]['member'].append(user_id)
            return True
        else:
            return False
    return False


def LeaveChannel(channel_name, user_id):
    if HasChannel(channel_name) and HasMember(channel_name, user_id):
        list_channel[channel_name]['member'].remove(user_id)
        if list_channel[channel_name]['leader_user_id'] == user_id and len(list_channel[channel_name]['member']) >= 1:
            list_channel[channel_name]['leader_user_id'] = list_channel[channel_name]['member'][0]
        if len(list_channel[channel_name]['member']) <= 0:
            del list_channel[channel_name]
            return True
    return False


# user_client
def AddDevice(address: Tuple[str, int], device_type: DeviceType, user_id: int, token: str,
              has_device_callable: Callable = None):
    host = address[0]
    port = address[1]
    if HasDevice(user_id, device_type) and has_device_callable:
        has_device_callable()
    if not HasUser(user_id):
        list_client[user_id] = {"token": token, "devices": {device_type: f"({host}, {port})"}}
    else:
        list_client[user_id]["devices"][device_type] = f"({host}, {port})"


def RemoveDevice(user_id, device_type: DeviceType, logout_callable: Callable = None):
    if HasDevice(user_id, device_type):
        del list_client[user_id]['devices'][device_type]
    if len(list_client[user_id]['devices'].keys()) <= 0:
        del list_client[user_id]
        if logout_callable:
            logout_callable()


def GetDevice(user_id: int, device_type: DeviceType):
    if HasDevice(user_id, device_type):
        return GetDevices(user_id)[device_type]


def GetAllDevice(user_id: int) -> List:
    _list = []
    for device in list_client[user_id]['devices'].keys():
        _list.append(eval(list_client[user_id]['devices'][device]))
    return _list


def HasUser(user_id: int):
    return user_id in list_client.keys()


def GetDevices(user_id: int) -> Dict:
    return list_client[user_id]['devices']


def HasDevice(user_id: int, device_type: DeviceType):
    if not HasUser(user_id):
        return False
    return device_type in GetDevices(user_id).keys()


def AllUser():
    return list_client

# room
